package com.googlecode.kipler.syntax.concept;

import com.googlecode.kipler.syntax.Role;

/**
 * This class represents a concept expression formed by some or all values
 * restrictions from description logics.
 * 
 * @author İnanç Seylan
 * 
 */
public class RoleQuantification extends Concept {
	/**
	 * The restriction constructor
	 * 
	 */
	public enum Constructor {
		/**
		 * Some values from restriction constructor
		 */
		SOME,
		/**
		 * All values from restriction constructor
		 */
		ALL;
	}

	/**
	 * The role name which this constructor is applied to
	 */
	private Role role;

	/**
	 * The type of the constructor
	 */
	private Constructor constructor;

	/**
	 * The concept that the values of this role come from
	 */
	private Concept concept;

	/**
	 * Default constructor
	 */
	public RoleQuantification() {

	}

	/**
	 * Constructor to initialize all the fields of this class by the given ones.
	 * 
	 * @param constructor
	 *            The type of the constructor
	 * @param role
	 *            The role name
	 * @param concept
	 *            The concept expression
	 */
	public RoleQuantification(Constructor constructor, Role role,
			Concept concept) {
		setConstructor(constructor);
		setRole(role);
		setConcept(concept);
	}

	/**
	 * @return the type of the constructor of this restriction.
	 */
	public Constructor getConstructor() {
		return constructor;
	}

	/**
	 * Sets the type of the constructor of this restriction.
	 * 
	 * @param constructor
	 *            The constructor to set.
	 */
	public void setConstructor(Constructor constructor) {
		this.constructor = constructor;
	}

	/**
	 * @return the concept expression.
	 */
	public Concept getConcept() {
		return concept;
	}

	/**
	 * Sets the concept expression.
	 * 
	 * @param concept
	 *            The concept expression to set
	 */
	public void setConcept(Concept concept) {
		this.concept = concept;
	}

	/**
	 * @return the name of the role that this restriction is applied to.
	 */
	public Role getRole() {
		return role;
	}

	/**
	 * Sets the name of the role that this restriction is applied to.
	 * 
	 * @param role
	 *            The role name to set
	 */
	public void setRole(Role role) {
		this.role = role;
	}

	/**
	 * @see tr.edu.ege.seagent.alcbi.syntax.description.VisitableConcept#accept(tr.edu.ege.seagent.alcbi.syntax.description.ConceptVisitor)
	 */
	public void accept(ConceptVisitor v) {
		v.visitRoleQuantification(this);
	}

	public Concept toggleNegated() {
		if (getConstructor().equals(Constructor.ALL)) {
			setConstructor(Constructor.SOME);
		} else {
			setConstructor(Constructor.ALL);
		}
		setConcept(getConcept().toggleNegated());
		return this;
	}

	public boolean isNegated() {
		return false;
	}

	/**
	 * @see tr.edu.ege.seagent.alcbi.syntax.description.Concept#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj != null && (obj.getClass().equals(this.getClass()))) {
			RoleQuantification other = (RoleQuantification) obj;
			return (this.isLeftBiased() == other.isLeftBiased()
					&& this.getConstructor().equals(other.getConstructor())
					&& this.getRole().equals(other.getRole()) && this
					.getConcept().equals(other.getConcept()));
		}
		return false;
	}

	/**
	 * @see tr.edu.ege.seagent.alcbi.syntax.description.Concept#hashCode()
	 */
	@Override
	public int hashCode() {
		return 17 * 37 + new Boolean(isLeftBiased()).hashCode()
				+ getConstructor().hashCode() + getConcept().hashCode()
				+ getRole().hashCode();
	}

	/**
	 * @see tr.edu.ege.seagent.alcbi.syntax.description.Concept#copy()
	 */
	public RoleQuantification copy() {
		RoleQuantification qr = new RoleQuantification();
		qr.setConstructor(getConstructor());
		qr.setRole(getRole().copy());
		qr.setConcept(getConcept().copy());
		qr.setLeftBiased(isLeftBiased());
		return qr;
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append(getConstructor());
		buffer.append("(");
		buffer.append(getRole().toString());
		buffer.append(", ");
		buffer.append(getConcept());
		buffer.append(")");
		return buffer.toString();
	}

	@Override
	public void setLeftBiased(boolean value) {
		super.setLeftBiased(value);
		getConcept().setLeftBiased(value);
	}
}
